package Logic;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import javax.swing.ImageIcon;

import Models.Dice;
import Models.Player;
import Rules.BoardRule;
import Tiles.Tile;

public class GameEngine {

	private List<Tile> tiles = new ArrayList<Tile>();
	private List<BoardRule> rules = new LinkedList<BoardRule>();
	private List<Player> players = new ArrayList<Player>();
	private List<Player> playersInGoal	= new ArrayList<Player>();
	List<Dice> dices = new LinkedList<Dice>();
	private ListIterator<Player> playerIt;
	private Player currentPlayer;

	private int steps;
	private boolean stepPlayers;
	private boolean gameEnd;
	
	public int getSteps() {
		return steps;
	}

	public void setSteps(int steps) {
		this.steps = steps;
	}

	public GameEngine(List<Dice> dices) {
		this.dices = dices;
		
		playerIt = players.listIterator();
		steps = 0;
		stepPlayers = true;
	}

	public int rollDice() {
		steps = 0;
		System.out.println(dices.get(0));
		for(Dice d : dices){
			steps += d.roll();
		}
		
		System.out.println("Player " +  currentPlayer + " rolled : " + steps);
		
		//execute all rules
		Iterator<BoardRule> ruleIterator = rules.iterator();
		while (ruleIterator.hasNext()) {
			ruleIterator.next().executeRule();
		}
		
		// Move player
		this.move(steps, currentPlayer);
		
		
		if (players.size() <= 0) {
			
			System.out.println("Game ended");
		} else if (stepPlayers) {
			this.nextPlayer();		
		}

		stepPlayers = true;
		return steps;
	}
	
	/**
	 * Add Tile to the gameBoard
	 * @param x
	 * @param y
	 * @param label
	 */
	void addTile(Tile t) {
		tiles.add(t);
	}
	
	public void addRule(BoardRule rule){
		rules.add(rule);
	}
	
	void addPlayer(String name, ImageIcon img) {
		Tile start 			= tiles.get(0);
		Player p 	= new Player(name, start, img);
		players.add(p);
		start.addPlayer(p);
	}
	
	public void move(int steps, Player p){
		//Get current tile and tileNumber
		Tile currentTile = p.getTile();
		int currentTileNumber = tiles.indexOf(currentTile);
		
		int tileNumberToGoTo = currentTileNumber + steps;
		
		//If going to tile <0 then go to 0
		if(tileNumberToGoTo < 0)
			tileNumberToGoTo = 0;
		else if(tileNumberToGoTo > tiles.size()-1)
			tileNumberToGoTo = tiles.size()-1;

		currentTile.removePlayer(p);
		Tile tileToGoTo = tiles.get(tileNumberToGoTo);
		p.setTile(tileToGoTo);
		
		tileToGoTo.rule(this);
	}
	
	public Player getCurrentPlayer(){
		return currentPlayer;
	}
	
	public List<Tile> getTileList(){
		return tiles;
	}

	public List<Player> getPlayerList(){
		return players;
	}
	public void inGoal(Player p) {
		playersInGoal.add(p);
		playerIt.remove();
		
		System.out.println("Player " +  p + " is in goal!");
	}

	void gameReady() {
		playerIt = players.listIterator();
		currentPlayer = playerIt.next();
	}

	public boolean isGameEnd() {
		
		return gameEnd;
	}
	
	public void setGameEnd(boolean gameEnd) {
		this.gameEnd = gameEnd;
	}

	public String getWinner() {
		return this.playersInGoal.get(0).getName();
	}
	
	public void prevPlayer() {
		if (playerIt.hasPrevious()) {
			playerIt.previous();
		}
		else {
			playerIt = players.listIterator(players.size());
		}
	}
	
	public boolean isStepPlayers() {
		return stepPlayers;
	}

	public void setStepPlayers(boolean stepPlayers) {
		this.stepPlayers = stepPlayers;
	}

	public void nextPlayer() {
		if (playerIt.hasNext()) {
			currentPlayer = playerIt.next();
		}
		else {
			playerIt = players.listIterator();
			currentPlayer = playerIt.next();
		}
	}
	
	public boolean hasPlayer(Player p) {
		return players.contains(p);
	}

	public List<Dice> getDices() {
		return dices;
	}

	public List<Player> getPlayersInGoal() {
		return playersInGoal;
	}

	public void setPlayersInGoal(List<Player> playersInGoal) {
		this.playersInGoal = playersInGoal;
	}
	
	public void addBoardRule(BoardRule boardRule) {
		rules.add(boardRule);
	}
}
